﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Aliphant.Datas;
using Aliphant.Interfaces;

namespace Aliphant.IoC
{
    public class Container : IContainer
    {
        public readonly Dictionary<Type, Registration> Registrations = new();
        public readonly object SyncRoot = new();
        public readonly Scope RootScope;

        public Container()
        {
            RootScope = new Scope(this);
            Register<IContainer, Container>(LifecycleType.Singleton);
        }

        public IContainer Register<TService, TImplementation>(LifecycleType lifecycle) where TImplementation : TService
        {
            return Register(typeof(TService), typeof(TImplementation), lifecycle);
        }

        public IContainer Register(Type serviceType, Type implementationType, LifecycleType lifecycle)
        {
            // 判断实现是否继承自服务
            if (!serviceType.IsAssignableFrom(implementationType))
                throw new ArgumentException($"Type {implementationType} is not assignable to {serviceType}");

            var registration = new Registration(
                implementationType,
                lifecycle,
                CreateInstanceFactory(implementationType));

            Registrations[serviceType] = registration;
            return this;
        }

        public object Resolve(Type serviceType)
        {
            return RootScope.Resolve(serviceType);
        }

        public T Resolve<T>()
        {
            return (T)Resolve(typeof(T));
        }

        public IScope CreateScope()
        {
            return new Scope(this);
        }


        private Func<IScope, object> CreateInstanceFactory(Type implementationType)
        {
            // 获取参数最常的构造函数
            var constructor = implementationType
                .GetConstructors()
                .OrderByDescending(c => c.GetParameters().Length)
                .First();

            // 获取构造函数的所有参数类型
            var paramTypes = constructor.GetParameters()
                .Select(p => p.ParameterType)
                .ToArray();

            return scope =>
            {
                var args = paramTypes.Select(t => scope.Resolve(t)).ToArray();
                // 作用域创建实例
                return constructor.Invoke(args);
            };
        }

        #region Dispose


        private bool disposedValue;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                }

                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
                // TODO: 将大型字段设置为 null
                disposedValue = true;
            }
        }

        // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        // ~Container()
        // {
        //     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
        //     Dispose(disposing: false);
        // }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }


        #endregion
    }


    public record Registration(Type ImplementationType, LifecycleType Lifecycle, Func<IScope, object> Factory)
    {
        public Registration MakeGenericType(params Type[] typeArguments)
        {
            var genericImplType = ImplementationType.MakeGenericType(typeArguments);
            return new Registration(genericImplType, Lifecycle,
                scope => scope.Resolve(genericImplType));
        }
    }
}
